#include "devices.h"
#include "my_api.h"
#include "trans_task.h"
#include "eeprom.h"
#include "tasks.h"

static uint8_t pwm_duty = 0;
static uint8_t pwm_en = 0;
static uint8_t pwm_count = 0;
static uint8_t init_flg = 0;
static sys_wake_type_t wake_type = wake_by_key;

sys_wake_type_t sys_get_wake_type()
{
    return wake_type;
}

void sys_set_wake_type(sys_wake_type_t type)
{
    wake_type = type;
}

static void per_motor_en(uint8_t en)
{
    pwm_en = en;
    if (en)
    {
        gpio_set_mode(motor_io, gpio_mode_output_pushpull);
    }
    else
    {
        gpio_set_level(motor_io, 0);
        gpio_set_mode(motor_io, gpio_mode_input);
        pwm_count = 0;
    }
}

uint8_t devices_get_usb_sta(void)
{
    return gpio_get_level(usb_in_io);
}

static void gpio_init()
{
    gpio_set_mode(esp_printf_io, gpio_mode_output_pushpull);
    gpio_set_level(esp_printf_io, 1);

    gpio_set_mode(key_io, gpio_mode_input);

    gpio_set_mode(motor_io, gpio_mode_input);

    gpio_set_mode(intr_lp_io, gpio_mode_input);
    gpio_set_mode(intr1_lsm_io, gpio_mode_input);
    gpio_set_mode(intr2_lsm_io, gpio_mode_input);

    gpio_set_mode(usb_in_io, gpio_mode_input);
}

static void sys_clk_init()
{
    stc_clk_config_t stcCfg;

    stcCfg.enClkSrc = ClkRCH;   // RCH  = 4M
    stcCfg.enHClkDiv = ClkDiv1; // HCLK = 4M/128
    stcCfg.enPClkDiv = ClkDiv1; // PCLK = 4M/128/8

    Clk_Init(&stcCfg);
    sys_frq_switch((sys_frq_t)mcu_sys_frq);
}

static void sys_tic_set(uint32_t sys_frq)
{
    stc_clk_systickcfg_t stcCfg;
    stcCfg.enClk = ClkRCH;
    stcCfg.u32LoadVal = sys_frq / 1000 - 1; // 1ms
    Clk_SysTickConfig(&stcCfg);
    SysTick_Config(stcCfg.u32LoadVal);
}

static void bat_init()
{
    cw2015_trans_cb_t cbs;
    cbs.iic_read_bytes = iic_read_bytes;
    cbs.iic_write_bytes = iic_write_bytes;
    cw2015_attach_trans_cb(&cbs);
    cw2015_init(cw_auto_init);
}

void devices_motor_set(uint8_t duty)
{
    if (getBit((uint32_t)&M0P_GPIO->P0IN + 3 * GPIO_GPSZ, 1) == 0) // ESP开机则强制关闭)
    {
        per_motor_en(0);
        return;
    }
    pwm_duty = duty;
    if (pwm_duty)
        per_motor_en(1);
    else
        per_motor_en(0);
}

void sys_frq_switch(sys_frq_t frq)
{
    Clk_SetRCHFreq((en_clk_freq_t)frq); // 更改时钟速率
    while (Clk_GetClkRdy(ClkRCH) == 0)
        ;
    sys_tic_set(Clk_GetHClkFreq()); // 设置滴答定时器
}

void devices_init(void)
{
    Clk_SetFunc(ClkFuncSwdPinIOEn, 1); // 关闭SWD接口

    stc_lpm_config_t stcLpmCfg; // 配置休眠模式为deep sleep
    stcLpmCfg.enSEVONPEND = SevPndDisable;
    stcLpmCfg.enSLEEPDEEP = SlpDpEnable;
    stcLpmCfg.enSLEEPONEXIT = SlpExtDisable;
    Lpm_Config(&stcLpmCfg);

    sys_clk_init();                          // 初始化时钟
    gpio_init();                             // 初始化gpio
    iic_init();                              // 初始化iic
    btn_attach_read_io_func(gpio_get_level); // 初始化按键接口
    btn_attach(key_io, 0);                   // 注册按键

    bat_init(); // 电池初始化

    rtc_task_init(eeprom_get_rtc_time()); // 初始化RTC
}

void sys_deep_sleep_start() // 开始休眠
{
    gpio_set_mode(txd1_io, gpio_mode_input_pullup); // 关串口
    gpio_set_irq(key_io, GpioIrqFalling, 1);        // 打开按键唤醒中断
    gpio_set_irq(usb_in_io, GpioIrqRising, 1);      // 打开USB唤醒中断

    Lpm_GotoLpmMode(); // 进入休眠

    // 唤醒
    while (Clk_GetClkRdy(ClkRCH) == 0) // 等待时钟稳定
        ;
    gpio_set_irq(key_io, GpioIrqFalling, 0);   // 关闭按键中断
    gpio_set_irq(usb_in_io, GpioIrqRising, 0); // 关闭USB唤醒中断
}

void sys_wake_esp_up()
{
    if (sys_get_esp_wake_sta())
        return;
    gpio_set_mode(txd1_io, gpio_mode_output_pushpull); // 切为输出
    gpio_set_level(txd1_io, 0);                        // 拉低唤醒ESP32
    gpio_set_level(txd1_io, 1);

    Gpio_SetFunc_UART1TX_P23(); // 开串口
}

void sys_restart_esp()
{
    if (sys_get_esp_wake_sta() == 0)
        return;
    gpio_set_level(esp_printf_io, 0);
    delay1ms(1);
    gpio_set_level(esp_printf_io, 1);
}

void sys_restart()
{
    key_value_msg("restart", NULL, 0); // 发布重启消息
    NVIC_SystemReset();
}

uint8_t sys_get_esp_wake_sta()
{
    if (init_flg)
        return 0;
    return (!gpio_get_level(esp_sta_io));
}

void sys_upload_wake_info()
{
    sys_wake_type_t wake_type = sys_get_wake_type();
    sys_wake_info_t wake_info = wake_key;
    if (wake_type == wake_by_usb)
        wake_info = wake_usb;
    else if (wake_type == wake_by_low_soc)
        wake_info = wake_low_soc;
    else if (wake_type == wake_by_alarm)
        wake_info = wake_alram;
    else if (wake_type == wake_by_mems)
        wake_info = wake_wrist;
    trans_packer_send_pack(esp_trans_get_handle(), "wake_info", &wake_info, sizeof(wake_info));
}

void sys_init_start()
{
    init_flg = 1;
    gpio_set_mode(esp_sta_io, gpio_mode_output_od);
    gpio_set_level(esp_sta_io, 0); // 下拉初始化状态，主处理器等待
}

void sys_init_end()
{
    gpio_set_mode(esp_sta_io, gpio_mode_input_pullup); // 初始化完成，释放状态，由主处理器管控状态
    init_flg = 0;
}

void sys_power_off()
{
    key_value_msg("power_off", NULL, 0);
    for (size_t i = 0; i < 2; i++)
    {
        devices_motor_set(5);
        btask_delay(100);
        devices_motor_set(0);
        btask_delay(100);
    }
    sys_deep_sleep_start();
}

uint8_t sys_chek_low_soc()
{
    if (sys_get_esp_wake_sta()) // ESP唤醒时由ESP自行管控
        return 0;
    cw2015_bat_info_t bat;
    cw2015_get_info(&bat);
    if (bat.soc <= auto_power_off_low_soc || bat.voltage <= auto_power_off_voltage)
    {
        if (devices_get_usb_sta() == 0)
            return 1;
    }
    if (sys_get_esp_wake_sta() == 0)
        key_value_msg("power_on", NULL, 0);
    return 0;
}

///////////////////////////中断入口////////////////////////////////////

void SysTick_Handler(void) // 系统心跳
{
    if (pwm_en)
    {
        pwm_count++;
        if (pwm_count == 10)
        {
            pwm_count = 0;
            if (pwm_duty)
                setBit((uint32_t)&M0P_GPIO->P0OUT + 2 * GPIO_GPSZ, 7, 1);
        }
        if (pwm_count == pwm_duty)
            setBit((uint32_t)&M0P_GPIO->P0OUT + 2 * GPIO_GPSZ, 7, 0);
    }
    if (pwm_en) // 电机使能
    {
        if (getBit((uint32_t)&M0P_GPIO->P0IN + 3 * GPIO_GPSZ, 1) == 0) // ESP开机则强制关闭
            per_motor_en(0);
    }

    btask_tick_inc(1);
    btn_tic_ms(1);
}

void Gpio_IRQHandler(uint8_t u8Param)
{
    *((uint32_t *)((uint32_t)&M0P_GPIO->P0ICLR + 3 * 0x40)) = 0; // 清P3中断
    *((uint32_t *)((uint32_t)&M0P_GPIO->P0ICLR)) = 0;            // P0

    if (gpio_get_level(key_io) == 0)
    {
        wake_type = wake_by_key;
        tasks_wake_esp();
        return;
    }
    if (gpio_get_level(usb_in_io) == 1)
    {
        wake_type = wake_by_usb;
        tasks_wake_esp();

        return;
    }
    if (gpio_get_level(intr_lp_io) == 0)
    {
        wake_type = wake_by_low_soc;
        tasks_wake_esp();
        return;
    }

    wake_type = wake_by_mems;
    tasks_memes_chek();
}
